namespace Xsxiaosa.Net
{
    using System;
    using System.Net;
    using System.Net.Sockets;
// jyj add
	using System.Reflection; 

    internal abstract class ProxyBase
    {
        // Methods
        public ProxyBase(Socket socket)
        {
            this._proxyUserName = null;
            this._proxyPassword = null;
            this._proxyHost = null;
            this._proxyPort = -1;
            this._asyncResult = null;
            this._socket = socket;
        }

        protected void Begin(string method, AsyncCallback callback, object state)
        {
            if (this._asyncResult != null)
            {
                throw new InvalidOperationException(Messages.GetString("AsyncCallPending"));
            }
            this._asyncResult = new ProxyAsyncResult(this, method, callback, state);
        }

        public abstract IAsyncResult BeginAccept(AsyncCallback callback, object state);

        public abstract IAsyncResult BeginConnect(IPEndPoint endPoint, AsyncCallback callback, object state);

        public abstract IAsyncResult BeginConnect(string serverName, int serverPort, AsyncCallback callback, object state);

        public abstract IAsyncResult BeginListen(ProxyBase controlSocket, AsyncCallback callback, object state);

        protected Exception CancelBegin(Exception e)
        {
            this._asyncResult = null;
            if ((e as SocketException) != null)
            {
                return new ProxySocketException(((SocketException) e));
            }
            return e;
        }

        public static ProxyBase Create(Socket socket, ProxyBase controlSocket)
        {
            if ((controlSocket as ProxyNone) != null)
            {
                return new ProxyNone(socket);
            }
            controlSocket.GetType();
            object[] objArray1 = new object[1];
            objArray1[0] = socket;
            ProxyBase base1 = ((ProxyBase) controlSocket.GetType().InvokeMember(null, BindingFlags.CreateInstance, null, null, objArray1));
            base1._proxyHost = controlSocket._proxyHost;
            base1._proxyPort = controlSocket._proxyPort;
            base1._proxyUserName = controlSocket._proxyUserName;
            base1._proxyPassword = controlSocket._proxyPassword;
            return base1;
        }

        public static ProxyBase Create(Socket socket, ProxyType type, string host, int port, string userName, string password)
        {
            ProxyBase base1;
            if (type != ProxyType.None)
            {
                if (host == null)
                {
                    throw new ProxySocketException(Messages.GetString("ArgumentNullHostname"), ProxySocketExceptionStatus.ProxyNameResolutionFailure);
                }
                if (host.Trim().Length == 0)
                {
                    throw new ProxySocketException(Messages.GetString("ArgumentEmptyHostname"), ProxySocketExceptionStatus.ProxyNameResolutionFailure);
                }
            }
            ProxyType type1 = type;
            switch (type1)
            {
                case ProxyType.Socks4:
                {
                    base1 = new ProxySocks4(socket);
                    goto Label_007C;
                }
                case ProxyType.Socks4a:
                {
                    base1 = new ProxySocks4a(socket);
                    goto Label_007C;
                }
                case ProxyType.Socks5:
                {
                    base1 = new ProxySocks5(socket);
                    goto Label_007C;
                }
                case ProxyType.HttpConnect:
                {
                    base1 = new ProxyHttpConnect(socket);
                    goto Label_007C;
                }
            }
            base1 = new ProxyNone(socket);
        Label_007C:
            base1._proxyHost = host;
            base1._proxyPort = port;
            if (userName != null)
            {
                base1._proxyUserName = userName;
            }
            else
            {
                base1._proxyUserName = "";
            }
            if (password != null)
            {
                base1._proxyPassword = password;
                return base1;
            }
            base1._proxyPassword = "";
            return base1;
        }

        public object End(IAsyncResult asyncResult, string method)
        {
            object[] objArray1;
            if (asyncResult == null)
            {
                throw new ArgumentNullException("asyncResult");
            }
            ProxyAsyncResult result1 = (asyncResult as ProxyAsyncResult);
            if (((result1 == null) || (result1.AsyncObject != this)) || (result1.Method != method))
            {
                objArray1 = new object[1];
                objArray1[0] = method;
                throw new ArgumentException(Messages.GetString("InvalidEndCall", objArray1));
            }
            result1.Wait();
            this._asyncResult = null;
            return result1.End(method);
        }

        protected void Finish()
        {
            ProxyAsyncResult result1 = this._asyncResult;
            if (result1 != null)
            {
                result1.Finish();
            }
        }

        protected void SetError(Exception e)
        {
            ProxyAsyncResult result1 = this._asyncResult;
            if (result1 == null)
            {
                return;
            }
            SocketException exception1 = (e as SocketException);
            if (exception1 == null)
            {
                result1.SetError(e);
                return;
            }
            result1.SetError(new ProxySocketException(exception1));
        }

        internal void SetSocket(Socket socket)
        {
            this._socket = socket;
        }


        // Properties
        protected int Available
        {
            get
            {
                int num1;
 //jyj modify               int num2;
                try
                {
                    num1 = this._socket.Available;
                    if (num1 > 0)
                    {
                        return num1;
                    }
                    if (!this._socket.Poll(1000, SelectMode.SelectRead))
                    {
                        return 0;
                    }
                    num1 = this._socket.Available;
                    if (num1 > 0)
                    {
                        return num1;
                    }
                    return -1;
                }
                catch (SocketException exception1)
                {
                    throw new ProxySocketException(exception1);
                }
 //jyj modify               return num2;
            }
        }

		public Socket Socket
		{
			get
			{
				return this._socket;
			}
		}


        // Fields
        protected ProxyAsyncResult _asyncResult;
        protected string _proxyHost;
        protected string _proxyPassword;
        protected int _proxyPort;
        protected string _proxyUserName;
        private Socket _socket;
    }}

